#ifndef MENU_H
#define MENU_H

#include <QtCore>
#include <QAction>
#include <QString>
#include <QWidget>
#include <QMap>
#include <QSet>
#include "hybridfw_global.h"

class QMainWindow;
class QWebFrame;
class HybridPluginManager;

class MenuItem : public QObject
{
    Q_OBJECT
public:

    MenuItem(const QString& label, const int id, const int parentId, const QString &handlerFunction, QAction *qAction) :
    						m_label(label), 
    						m_id(id), 
    						m_parentId(parentId), 
    						m_handlerFunction(handlerFunction), 
    						m_qAction(qAction)
    {}

    QString m_label;
    int     m_id;
    int     m_parentId;
    QString m_handlerFunction;
    QAction *m_qAction;
};


class DLL_EXPORT CoreMethods : public QObject
{
    Q_OBJECT
    
public:
    CoreMethods(QMainWindow *parentWindow, 
				QWebFrame *webFrame, 
				HybridPluginManager* pluginManager,
				QString identifier);

signals:
	/**
	 * Signal when item is selected,
	 * 
	 * @param id Id of the selected item.
	 */
    void itemSelected(int id);
    
    /**
     * Signal when menu is shown.
     */
    void menuOnShow();

public slots:

    /**
      * Call the appendMenuItem method to add a menu item to the top level of the options menu list.
      *
      * Call the append method to add a child menu item to the parent menu item in the options menu list.
      * This results in the creation of a submenu list in the menu tree. Use this method to create a cascading submenu when needed.
      *
      * Menu items are shown on the options menu list in the order in which they are appended.
      *
      * @param label A text string that defines the label for the menu item.
      * @param id A unique integer that identifies the menu item.
      * @param parentId A unique integer that identifies the parent menu item, 0 if no parent exists.
      * @param onSelect Name of the event handler for the event of when the menu item is selected.
      */
    void appendMenuItem(const QString &label, const int id, const int parentId, const QString &onSelect);

    /**
      * Call the setDimmed method to show or hide an existing menu item.
      * By default, a menu item is shown when it is appended to the options menu.
      *
      * @param id The id of the menu item to be hidden or shown
      * @param flag True to hide the menu item, and false to show the menu item.
      */
    void setDimmed(const int id, bool flag);

    /**
      * Call the remove method to remove a menu item and its children (if any).
      *
      * @param id The id of the menu item to be removed
      */
    void remove(const int id);

    /**
      * Call the clear method to delete all the menu items in the options menu pane.
      * This operation will also clear all submenus if such exist.
      *
      */
    void clear();

    /**
      * Call the showSoftkeys method to display the softkey pane at all times.
      *
      */
    void showSoftkeys();

    /**
      * Call the hideSoftkeys method to hide the softkey pane.
      *
      */
    void hideSoftkeys();

    /**
      * Call the setLeftSoftkeyLabel method to customize the label and the operation associated with the left softkey.
      *
      * By default, the left softkey of a device is assigned to the "Options" function, which invokes a list of menu items.
      * The default label depends on the current used system language (Options for English).
      *
      * @param label A text string specifies the label to be shown on the left softkey.
      * @param callbackfunc A reference to the callback function, which will be called by the system when the left softkey is pressed.
      */
    void setLeftSoftkeyLabel(const QString &label, const QString &callbackfunc);

    /**
      * Call the setRightSoftkeyLabel method to customize the label and the operation associated with the right softkey.
      *
      * By default, the right softkey of a device is assigned to the "Exit" function, which terminates a running widget.
      * The default label depends on the current used system language (Exit for English).
      *
      * @param label A text string specifies the label to be shown on the right softkey.
      * @param callbackfunc A reference to the callback function, which will be called by the system when the right softkey is pressed.
      */
    void setRightSoftkeyLabel(const QString &label, const QString &callbackfunc);

    void menuHandler();
    void menuItemHandler();
    void customSoftkeyHandler();
    void debugLog(const QString &line);
    
    /**
      * The setPreferenceForKey method allows a key to be stored along with its associated preference.
      * The arguments are like name and value pairs. The preference value for the key is stored persistently,
      * so if the widget or device is restarted, the value is retained. However, the values stored by a widget
      * are removed when a widget is uninstalled from the device. This includes the case when a widget is
      * reinstalled; where the old widget is uninstalled, the new widget is installed.
      *
      * An existing preference can be overwritten with a new value by simply calling the method with the same key and new value.
      *
      * A stored preference for a key can be removed by calling the method with the preference argument set to null
      *
      * @param value String defining the value for the key.
      * @param key String defining the preference key.
      */
    void setPreferenceForKey(const QString &value, const QString &key);

    /**
      * The preferenceForKey method allows a previously stored preference to be restored.
      *
      * @param key A text string specifying the name that represents the preference to be restored.
      */
    QString preferenceForKey(const QString &key);

    /**
      * The setDisplayPortrait method changes the orientation of a widget's screen to the portrait mode.
      */
    void setDisplayPortrait();

    /**
      * The setDisplayLandscape method changes the orientation of a widget's screen to the landscape mode.
      */
    void setDisplayLandscape();

    /**
      * The navigation mode in a widget can be toggled between a cursor and a tabbed navigation mode.
      * By default, the browsing mode of a widget is set to use a cursor (pointer).
      * The setNavigationEnabled method is used for changing the widget's navigation mode.
      *
      * The argument navigationType is of Boolean type and can be set to true or false to toggle the navigation mode between the cursor mode and the tab mode respectively.
      */
    void setNavigationEnabled(bool mode);

    /**
      *  The navigation mode in a widget can be set to cursor, tabbed, or none.
      *  By default, the browsing mode of a widget is set to use a cursor (pointer).
      *  The setNavigationType method is used for changing the widget's navigation mode.
      *
      *  The argument type is a String and can be set to:
      *
      *  cursor for cursor mode.
      *  tabbed for tab mode.
      *  none for no navigation mode. In this mode, WRT passes all events to the application.
      *  This includes all key events for non-touch devices and all events for
      *  touch devices. The application must handle all events.
      */
    void setNavigationType(const QString &navigationType);

    void prepareForTransition(const QString &transitionMode);

    void performTransition();

    /**
      *  The openApplication method enables a widget to launch an S60 mobile application in the stand-alone mode.
      *
      * @param Uid A hexadecimal number that specifies the UID of the S60 application to be activated.
      * @param param A text string defining a possible argument string that is accepted by the S60 application
      * to be activated. The arguments vary between applications. For example, when defined for the Web Browser
      * for S60 application (UID: 0x10008D39), the parameter "4"+"<Space>"+"<url>" tells the browser to open with
      * content from a specific URL. The parameter "5" launches the browser with the Start page open. You can also use
      * an empty string with any application, which results in launching the specified application with default behavior.
      *
      */
    void openApplication(const int Uid, const QString &param);

    /**
      *  The openURL method opens a specified link in the Web Browser for S60 in the stand-alone mode.
      *  The widget remains open but is sent to the background.
      *
      * @param url A compact string specifying a link to a resource to be opened. The URL string format is
      *  compliant with the RFC-1738 specification and must be encoded if it contains non-ASCII characters.
      *
      */
    void openURL(const QString &url);

    bool rotationSupported();

    QObject *getPlugin(const QString &pluginName);
    
    QString widgetIdentifier();
    
private:

    bool eventFilter(QObject *object, QEvent *event);
    MenuItem *menuItem(QAction *act);
    void removeSoftkey(bool rightSoftkey);

    QMainWindow             *m_parentWindow;
    QWebFrame               *m_webFrame;
    QMap<int, MenuItem*>     m_menuItems; // <id, MenuItem*>
    MenuItem                *m_leftSoftkey;
    MenuItem                *m_rightSoftkey;
    HybridPluginManager		*m_pluginManager;
    QSet<QString>            m_menuItemHandlerFunctions;
    QString					 m_identifier;
};

#endif // MENU_H
